package util;

import dao.DataManager;
import model.*;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

public class CinemaUtil {
    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
    private static final DataManager dataManager = DataManager.getInstance();

    // 生成唯一ID
    public static String generateUniqueId() {
        return UUID.randomUUID().toString().substring(0, 8);
    }

    // 打印分隔线
    public static void printDivider() {
        System.out.println("------------------------------------------------------");
    }

    // 打印电影信息列表
    public static void printMovies(List<Movie> movies) {
        if (movies.isEmpty()) {
            System.out.println("没有找到电影信息");
            return;
        }

        for (int i = 0; i < movies.size(); i++) {
            System.out.println((i + 1) + ". " + movies.get(i).getTitle());
        }
    }

    // 打印场次信息列表
    public static void printScreenings(List<Screening> screenings) {
        if (screenings.isEmpty()) {
            System.out.println("没有找到场次信息");
            return;
        }

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
        for (int i = 0; i < screenings.size(); i++) {
            Screening s = screenings.get(i);
            System.out.println((i + 1) + ". " + s.getMovie().getTitle() + " | " + 
                              s.getHall().getName() + " | " + 
                              s.getStartTime().format(formatter) + " | " +
                              s.getPrice() + "元");
        }
    }

    // 打印用户信息列表
    public static void printUsers(List<User> users) {
        if (users.isEmpty()) {
            System.out.println("没有找到用户信息");
            return;
        }

        System.out.printf("%-8s %-10s %-12s %-12s %s\n", "用户ID", "用户名", "用户类型", "手机号", "注册时间");
        printDivider();
        for (User user : users) {
            System.out.printf("%-8s %-10s %-12s %-12s %s\n", 
                user.getId(),
                user.getUsername(),
                user.getUserType(),
                user.getPhoneNumber(),
                user.getRegistrationTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")));
        }
    }

    // 打印座位信息
    public static void printSeats(boolean[][] seats) {
        int rows = seats.length;
        int cols = seats[0].length;

        // 打印列号
        System.out.print("    ");
        for (int j = 0; j < cols; j++) {
            System.out.printf("%-3d", j + 1);
        }
        System.out.println();

        // 打印座位
        for (int i = 0; i < rows; i++) {
            System.out.printf("%-3d ", i + 1);
            for (int j = 0; j < cols; j++) {
                if (seats[i][j]) {
                    System.out.print("X  "); // 已售
                } else {
                    System.out.print("O  "); // 空闲
                }
            }
            System.out.println();
        }
        
        System.out.println("注：O表示空闲座位，X表示已售座位");
    }

    // 获取指定日期范围内的场次
    public static List<Screening> getScreeningsByDateRange(LocalDate startDate, int days) {
        LocalDateTime startDateTime = startDate.atStartOfDay();
        LocalDateTime endDateTime = startDate.plusDays(days).atStartOfDay();
        
        return dataManager.getAllScreenings().stream()
                .filter(s -> !s.getStartTime().isBefore(startDateTime) && s.getStartTime().isBefore(endDateTime))
                .sorted((s1, s2) -> s1.getStartTime().compareTo(s2.getStartTime()))
                .collect(Collectors.toList());
    }

    // 获取当前日期的场次
    public static List<Screening> getTodayScreenings() {
        return getScreeningsByDateRange(LocalDate.now(), 1);
    }

    // 获取当前一周的场次
    public static List<Screening> getWeekScreenings() {
        return getScreeningsByDateRange(LocalDate.now(), 7);
    }

    // 获取未来三天的场次
    public static List<Screening> getThreeDayScreenings() {
        return getScreeningsByDateRange(LocalDate.now(), 3);
    }

    // 自动排片
    public static List<Screening> autoScheduleScreenings(List<Movie> movies, List<Hall> halls, LocalDate startDate, int days) {
        List<Screening> newScreenings = new ArrayList<>();
        LocalDate endDate = startDate.plusDays(days);
        
        // 排片时间段
        LocalTime[] timeSlots = {
            LocalTime.of(10, 0),  // 10:00
            LocalTime.of(13, 0),  // 13:00
            LocalTime.of(16, 0),  // 16:00
            LocalTime.of(19, 0),  // 19:00
            LocalTime.of(22, 0)   // 22:00
        };
        
        // 按评分排序电影
        List<Movie> sortedMovies = movies.stream()
                .sorted((m1, m2) -> Double.compare(m2.getRating(), m1.getRating()))
                .collect(Collectors.toList());
        
        // 为每个日期生成场次
        for (LocalDate date = startDate; !date.isAfter(endDate); date = date.plusDays(1)) {
            boolean isWeekend = date.getDayOfWeek().getValue() >= 6; // 周末 (6=周六，7=周日)
            
            for (Hall hall : halls) {
                for (int timeIndex = 0; timeIndex < timeSlots.length; timeIndex++) {
                    LocalDateTime screeningTime = LocalDateTime.of(date, timeSlots[timeIndex]);
                    
                    // 如果已经过了当前时间，则不再排片
                    if (screeningTime.isBefore(LocalDateTime.now())) {
                        continue;
                    }
                    
                    // 选择电影 - 黄金时段（周末、晚上）优先安排高评分电影
                    int movieIndex;
                    if ((isWeekend || timeIndex >= 3) && !sortedMovies.isEmpty()) { // 晚上时段(19:00和22:00)或周末
                        movieIndex = 0; // 最高评分电影
                    } else {
                        // 平日白天时段轮流安排电影
                        movieIndex = (timeIndex + date.getDayOfMonth()) % sortedMovies.size();
                    }
                    
                    Movie movie = sortedMovies.get(movieIndex);
                    
                    // 设置票价 - 黄金时段票价较高
                    double price;
                    if (isWeekend) {
                        price = 60.0; // 周末基础票价
                    } else if (timeIndex == 0) {
                        price = 35.0; // 平日早场
                    } else if (timeIndex >= 3) {
                        price = 50.0; // 平日晚场
                    } else {
                        price = 40.0; // 平日午间场
                    }
                    
                    // 创建场次
                    Screening screening = new Screening(
                        generateUniqueId(),
                        movie,
                        hall,
                        screeningTime,
                        price
                    );
                    
                    newScreenings.add(screening);
                }
            }
        }
        
        return newScreenings;
    }

    // 记录日志
    public static void addLog(String operationType, String username) {
        dataManager.addLog(new LogEntry(operationType, username));
    }
} 